#include "downwidget.h"
#include <QByteArray>
#include <QDebug>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QFile>
//
DownWidget::DownWidget(QWidget *parent)
    : QWidget(parent)
{
    tcpServer = new QTcpServer(this);
    tcpSocket = nullptr;

    listenButton = new QPushButton("start");
    listenLineEdit = new QLineEdit("8888");
    listenPortLabel = new QLabel("port");
    openFileButton = new QPushButton("open");

    infoTextEdit = new QTextEdit;

    QVBoxLayout *mainLayout = new QVBoxLayout(this);
    QHBoxLayout *portLayout = new QHBoxLayout(this);


    portLayout->addWidget(listenPortLabel);
    portLayout->addWidget(listenLineEdit);
    portLayout->addWidget(listenButton);
    portLayout->addWidget(openFileButton);

    mainLayout->addWidget(infoTextEdit);
    mainLayout->addLayout(portLayout);

    setLayout(mainLayout);


    connect(listenButton, &QPushButton::clicked, this, &DownWidget::ListenButtonClickedSlot);
    connect(openFileButton, &QPushButton::clicked, this, &DownWidget::OpenFileSlot);
}

DownWidget::~DownWidget()
{
    if((tcpSocket != nullptr) && tcpSocket->isOpen())
    {
        tcpSocket->close();
    }

    if((tcpServer != nullptr) && (tcpServer->isListening()))
    {
        tcpServer->close();
    }
}

void DownWidget::OpenFileSlot()
{
    QString fileName = QFileDialog::getOpenFileName(this, "open file");
    qDebug() << fileName;

    QFile file(fileName);
    if (!file.open(QIODevice::ReadOnly))
        return;

    binDatArr = file.readAll();

    file.close();

    qDebug() << "file size = " << binDatArr.size();

}

void DownWidget::NewConnectSlot()
{
    qDebug() << "newConnectSlot";
    infoTextEdit->append("newConnectSlot");
    tcpSocket = tcpServer->nextPendingConnection();
    connect(tcpSocket, &QTcpSocket::channelReadyRead, this, &DownWidget::SocketReadyReadSlot);
}

void DownWidget::SocketReadyReadSlot()
{
    infoTextEdit->append("read dat");
    QByteArray datArray = tcpSocket->readAll();
    infoTextEdit->append(datArray.toHex(' '));
    //tcpSocket->write(datArray);
    if(checkDat(datArray.data(), datArray.size()))
    {
        infoTextEdit->append("checkDat Ok");
        DatHandle(datArray);
    }
}

void DownWidget::DatHandle(QByteArray &datArr)
{
    const CommonPack *pPack = (const CommonPack*)datArr.data();
    FunctionPack *pFuncPack = (FunctionPack*)pPack->dat;
    uint16_t packSize = 0;
    uint16_t packIndex = 0;
    int packSum = 0;
    FunctionPack head;
    ResourceAckPack sourceAckPack;
    QByteArray ack;
    switch (pFuncPack->functionCode)
    {
    case 0x0001:
        packSize = *((uint16_t*)pFuncPack->dat);
        qDebug() << "packSize = " << packSize;
        if(packSize < 0)
        {
            return;
        }

        packSum = binDatArr.size() / packSize;
        datArrList.clear();
        for(int i = 0; i < packSum; i++)
        {
            datArrList.append(binDatArr.mid(i * packSize, packSize));
        }
        datArrList.append(binDatArr.mid(packSize * packSum));
        qDebug() << "datArrList.size()" << datArrList.size();
        sourceAckPack.functionCode = 0x8001;
        sourceAckPack.statusCode = 0x0000;
        sourceAckPack.sourceSize = binDatArr.size();
        sourceAckPack.packSum = datArrList.length();
        ack.append((char*)&sourceAckPack, sizeof (sourceAckPack));

        break;

    case 0x0002:
        packIndex = *((uint16_t*)pFuncPack->dat);
        infoTextEdit->append(QString("packIndex = %1").arg(packIndex));
        if(packIndex < datArrList.length())
        {
            head.functionCode = 0x8002;
            head.statusCode = 0x0000;
            ack.append((char*)&head, sizeof (head));
            ack.append((char*)&packIndex, sizeof (packIndex));
            ack.append(datArrList.at(packIndex));
            infoTextEdit->append("ack Size = " + QString("%1").arg(ack.size()));
        }
        break;

    default:
        qDebug() << "err -----------";
    }
    SendPack(ack, pPack->packId);
}

void DownWidget::ListenButtonClickedSlot()
{
    infoTextEdit->append("listening......");
    if(!tcpServer->isListening())
    {
        listenButton->setText("restart");
        tcpServer->listen(QHostAddress::Any, listenLineEdit->text().toUShort());
        connect(tcpServer, &QTcpServer::newConnection, this, &DownWidget::NewConnectSlot);
    }
    else
    {
        disconnect(tcpServer, &QTcpServer::newConnection, this, &DownWidget::NewConnectSlot);
        tcpServer->close();
        tcpServer->listen(QHostAddress::Any, listenLineEdit->text().toUShort());
        connect(tcpServer, &QTcpServer::newConnection, this, &DownWidget::NewConnectSlot);
        listenButton->setText("restart");
    }
}


bool DownWidget::SendPack(QByteArray &dat, uint16_t packId)
{
    CommonPack pack;
    pack.head = PACK_HEAD;
    pack.datalen = dat.size();
    pack.packId = packId;
    pack.crc = 0x00;
    const uint8_t *pDat = (const uint8_t*)dat.data();
    for(int i = 0; i < dat.size(); i++)
    {
        pack.crc += *pDat++;
    }

    QByteArray ack((char*)&pack, sizeof(pack));
    ack.append(dat);
    tcpSocket->write(ack);
    infoTextEdit->append("Tx Size = " + QString("%1").arg(ack.size()));
    qDebug() << "ack = " << ack.toHex(' ');

    return true;
}

bool DownWidget::checkDat(const char *pDat, uint16_t dataLen)
{
    const CommonPack *pPack = (const CommonPack*)pDat;
    if(pPack->head != PACK_HEAD)
    {
        qDebug() << "head err";
        return false;
    }

    if(dataLen < pPack->datalen + sizeof (CommonPack))
    {
        qDebug() << "datlen err";
        return false;
    }

    uint16_t crc = 0;
    for(uint16_t i = 0; i < pPack->datalen; i++)
    {
        crc += pPack->dat[i];
    }

    if(pPack->crc != crc)
    {
        qDebug() << "crc err";
        return false;
    }


    return true;
}
